package openase.audiosearch.client.search.controller;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;

import openase.audio.AudioUtils;
import openase.audio.record.AudioRecorder;
import openase.audio.record.AudioRecordingException;
import openase.audio.record.MicrophoneAudioRecorder;
import openase.audiosearch.client.ClientProperties;
import openase.audiosearch.comm.CommUtil;
import openase.audiosearch.comm.request.AudioSearch;
import openase.audiosearch.comm.request.encoder.facade.RequestEncoderFacade;
import openase.audiosearch.comm.response.ExecutionError;
import openase.audiosearch.comm.response.Response;
import openase.audiosearch.comm.response.SearchResult;
import openase.audiosearch.comm.response.UnknownRequest;
import openase.audiosearch.comm.response.decoder.facade.ResponseDecoderFacade;


public class AudioSearchController {

	public byte[] record(int durationInSecs) throws AudioRecordingException {
		AudioRecorder recorder = new MicrophoneAudioRecorder();

		byte[] record = recorder.record(AudioUtils.getRecordingFormat(), durationInSecs, TimeUnit.SECONDS);
		return record;
	}

	public String search(byte[] recordedAudio) throws IOException {
		SocketChannel channel = CommUtil.connect(ClientProperties.getServerIP(), ClientProperties.getServerPort());

		int maxResults = ClientProperties.getMaxResults();
		AudioSearch search = new AudioSearch(recordedAudio, maxResults);

		ByteBuffer requestBuffer = RequestEncoderFacade.encode(search);
		CommUtil.send(channel, requestBuffer);

		ByteBuffer responseBuffer = CommUtil.recv(channel);
		Response response = ResponseDecoderFacade.decode(responseBuffer);

		if (response instanceof ExecutionError) {
			throw new RuntimeException("An error occurred in the server while registering the audio: " + ((ExecutionError) response).getErrorMessage());
		}
		if (response instanceof UnknownRequest) {
			throw new RuntimeException("The server did not recognize the request");
		}
		if (response instanceof SearchResult) {
			return ((SearchResult) response).getResult();
		}
		// an unknown response has been received
		throw new RuntimeException("The response from the server could not be recognized: " + response);
	}

}
